package cn.xeblog.server.action.pina;

import cn.xeblog.commons.entity.User;
import cn.xeblog.server.config.ServerConfig;
import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author eleven
 * @date 2024/11/27 14:42
 * @apiNote
 */
@Slf4j
public class LimitUtil {
    private static Map<User, Limiter> limiterMap = new ConcurrentHashMap<>();

    private static final Timer timer = new Timer();
    static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final ServerConfig serverConfig = ServerConfig.getConfig();
    public static boolean checkLimit(User user) {
        Limiter limiter = Optional.ofNullable(limiterMap.get(user))
                .orElse(Limiter.defaultLimiter(serverConfig));
        // 限制中
        if (limiter.getLimitFlag()) {
            return true;
        }
        int msgCount = limiter.getMsgCount() + 1;
        limiter.setMsgCount(msgCount);
        if (msgCount >= limiter.getCountLimit()) {
            limiter.setLimitFlag(true);
            limiter.setCountLimit(limiter.getCountLimit() >> 1);
            limiter.setLimitTime(limiter.getLimitLevel() << 1);
            limiter.setLimitLevel(limiter.getLimitLevel() << 1);
        }
        limiterMap.put(user, limiter);
        return false;
    }

    public static void startLimiterTask() {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                Date now = new Date();
                Calendar instance = Calendar.getInstance();
                instance.setTime(now);
                int hour = instance.get(Calendar.HOUR_OF_DAY);
                if (hour >= 7 && hour <= 22) {
                    limiterMap.forEach((k,v) -> {
                        if (!v.getLimitFlag()) {
                            limiterMap.put(k, Limiter.defaultLimiter(serverConfig));
                        } else {
                            int limitTime = v.getLimitTime() - 1;
                            v.setLimitTime(limitTime);
                            if (limitTime == 0) {
                                int limitLevel = v.getLimitLevel() >> 1;
                                v.setLimitLevel(limitLevel);
                                if (limitLevel == serverConfig.getLimitTime() ) {
                                    v.setLimitFlag(false);
                                    v.setCountLimit(serverConfig.getMaxLimit());
                                }
                            }
                            limiterMap.put(k, v);
                        }
                    });
                } else {
                    limiterMap.clear();
                }
            }
        };
        Date firstTime = getNextMinutes();
        long period = TimeUnit.MINUTES.toMillis(1);    // 设置每隔一分钟执行一次
        timer.scheduleAtFixedRate(task, firstTime, period);
    }

    public static Date getNextMinutes() {
        Calendar calendar = Calendar.getInstance();
        log.info("==> 计时器：当前时间 = " + dateFormat.format(calendar.getTime()));

        calendar.set(Calendar.MILLISECOND, 0);  // 清空毫秒
        calendar.set(Calendar.SECOND, 0);       // 清空秒
        calendar.add(Calendar.MINUTE, 1);     // 添加1分钟 用预测试

        Date nextMinutes = calendar.getTime();
        log.info("==> 计时器：开始时间 = " + dateFormat.format(nextMinutes));
        return nextMinutes;
    }

    public static void main(String[] args) {
        System.out.println(dateFormat.format(getNextMinutes()));
    }
}
